package com.leaf.user.rule;

import java.util.List;
import java.util.Random;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

/**
 * 自定义负载均衡策略、模拟随机 RandomRule
 * 
 * 如果两次都随机到一个服务，则跳过，再随机一次
 * 
 * @Title:
 * @Description:
 * @Author: leaf
 * @Since:2019年6月28日
 * @Version:1.1.0
 */
public class LeafRule extends AbstractLoadBalancerRule {

	Random rand;

	public LeafRule() {
		rand = new Random();
	}

	private int nowIndex = -1, // 当前下标
			lastIndex = -1, // 最后一次下标
			skipIndex = -1; // 跳过的下标

	public Server choose(ILoadBalancer lb, Object key) {

		if (lb == null) {
			return null;
		}
		Server server = null;

		while (server == null) {
			if (Thread.interrupted()) {
				return null;
			}

			// up 状态的服务
			List<Server> upList = lb.getReachableServers();
			List<Server> allList = lb.getAllServers();

			int serverCount = allList.size();
			if (serverCount == 0) {
				/*
				 * No servers. End regardless of pass, because subsequent passes only get more
				 * restrictive.
				 */
				return null;
			}

			int index = rand.nextInt(serverCount);
			System.out.println("当前下标：" + index);

			if (skipIndex > 0 && index == skipIndex) {
				System.out.println("跳过下标：" + index);
				index = rand.nextInt(serverCount);
				System.out.println("跳过后的下标：" + index);
			}

			skipIndex = -1;
			nowIndex = index;

			// 如果当前下标等于最后一次下标，记录下一次需要跳过的下标
			if (nowIndex == lastIndex) {
				System.out.println("下一次需要跳过的下标：" + index);
				skipIndex = nowIndex;
			}

			lastIndex = nowIndex;

			server = upList.get(index);

			if (server == null) {
				/*
				 * The only time this should happen is if the server list were somehow trimmed.
				 * This is a transient condition. Retry after yielding.
				 */
				Thread.yield();
				continue;
			}

			if (server.isAlive()) {
				return (server);
			}

			// Shouldn't actually happen.. but must be transient or a bug.
			server = null;
			Thread.yield();
		}

		return server;
	}

	@Override
	public Server choose(Object key) {
		return choose(getLoadBalancer(), key);
	}

	@Override
	public void initWithNiwsConfig(IClientConfig clientConfig) {
		// TODO Auto-generated method stub

	}

}
